<?php
/**
 * 是将日期转化为一个对象去操作.
 *
 * @author Qian Su <aoxue.1988.su.qian@163.com>
 * @copyright ©2003-2103 phpwind.com
 * @license http://www.windframework.com
 *
 * @version $Id: WindGeneralDate.php 2973 2011-10-15 19:22:48Z yishuo $
 */
class WindGeneralDate
{
    /**
     * 填充展示.
     *
     * @var int
     */
    const FILL = 0;

    /**
     * 数字展示.
     *
     * @var int
     */
    const DIGIT = 1;

    /**
     * 文本展示.
     *
     * @var int
     */
    const TEXT = 2;

    /**
     * 默认格式化.
     *
     * @var string
     */
    const DEFAULT_FORMAT = 'Y-m-d H:i:s';

    /**
     * unix时间戳.
     *
     * @var int
     */
    private $time = 0;

    /**
     * 根据输入的日期格式转化为时间戳进行属性time初始化.
     *
     * mktime函数，在只有输入一个年份的时候，就会默认转化为上一年的最后一天，输入一个月份并且缺省输入day的时候，
     * 会转化为上个月的最后一天。所以这种情况需要注意。
     * 如果该构造函数没有参数传入的时候，得到的日期不是期望的当前日期，而是上两年的11月的30日
     *
     * 如果月份为空：如果年份为空，则取当前月份；否则取1
     * 如果日期为空：如果年份为空，则取当前日期，否则取1
     * 如果小时为空：如果年份为空，则取当前小时
     * 如果分为空：如果年份为空，则取当前分
     * 如果秒为空：如果年份为空，则取当前秒
     * 如果年份为空：取当前年份
     *
     * @param int $year    年,默认为null，获取当前年
     * @param int $month   月,默认为null获取当前月
     * @param int $day     日,默认为null获取当前日期
     * @param int $hours   小时,默认为null获取当前小时
     * @param int $minutes 分,默认为null获取当前分钟
     * @param int $second  秒,默认为null获取当前秒
     */
    public function __construct($year = null, $month = null, $day = null, $hours = null, $minutes = null, $second = null)
    {
        $time = time();
        !$month && ((!$year) ? $month = date('m', $time) : $month = 1);
        !$day && ((!$year) ? $day = date('d', $time) : $day = 1);
        !$hours && !$year && $hours = date('H', $time);
        !$minutes && !$year && $minutes = date('i', $time);
        !$second && !$year && $second = date('s', $time);
        !$year && $year = date('Y', $time);
        $this->time = mktime($hours, $minutes, $second, $month, $day, $year);
    }

    /**
     * 获取当前时间所在月的天数.
     *
     * @return string
     */
    public function getDaysInMonth()
    {
        return date('t', $this->time);
    }

    /**
     * 获取当前时间所在年的天数.
     *
     * @return int 如果是闰年返回366否则返回365
     */
    public function getDaysInYear()
    {
        return $this->isLeapYear() ? 366 : 365;
    }

    /**
     * 所表示当前日期是该年中的第几天。
     *
     * @return int 返回时该年中的第几天
     */
    public function getDayOfYear()
    {
        return date('z', $this->time) + 1;
    }

    /**
     * 表示当前日期为该月中的第几天。
     *
     * @return int
     */
    public function getDayOfMonth()
    {
        return date('j', $this->time);
    }

    /**
     * 表示当前日期是该星期中的第几天。
     *
     * @return int
     */
    public function getDayOfWeek()
    {
        return date('w', $this->time) + 1;
    }

    /**
     * 判断当前日期所在年的第几周.
     *
     * @return int
     */
    public function getWeekOfYear()
    {
        return date('W', $this->time);
    }

    /**
     * 获取当前日期的年份.
     *
     * @param bool $format 是否返回四位格式的年份或是两位格式的年份，默认为true则以Y返回四位数
     *
     * @return string
     */
    public function getYear($format = true)
    {
        return date($format ? 'Y' : 'y', $this->time);
    }

    /**
     * 获当前日期的取月份.
     *
     * @param int $display 显示类型，默认为0，则显示两位的月份
     *
     * @return string
     */
    public function getMonth($display = self::FILL)
    {
        if (self::FILL == $display) {
            return date('m', $this->time);
        } elseif (self::DIGIT == $display) {
            return date('n', $this->time);
        } elseif (self::TEXT == $display) {
            return date('M', $this->time);
        }

        return date('n', $this->time);
    }

    /**
     * 获取当前日期的天数.
     *
     * @param string $display 显示类型，默认为0，显示两位的日期
     *
     * @return string
     */
    public function getDay($display = self::FILL)
    {
        if (self::FILL == $display) {
            return date('d', $this->time);
        } elseif (self::DIGIT == $display) {
            return date('j', $this->time);
        } elseif (self::TEXT == $display) {
            return date('jS', $this->time);
        }

        return date('j', $this->time);
    }

    /**
     * 获取当前日期的星期
     *
     * @param string $display 显示类型，默认为0，返回数字表示的星期中的第几天
     *
     * @return string
     */
    public function getWeek($display = self::FILL)
    {
        if (self::FILL == $display || self::DIGIT == $display) {
            return date('w', $this->time);
        } elseif (self::TEXT == $display) {
            return date('D', $this->time);
        }

        return date('N', $this->time);
    }

    /**
     * 获取当前日期的12小时制时间.
     *
     * @param string $display 显示类型，默认为0，显示两位的小时
     *
     * @return string
     */
    public function get12Hours($display = self::FILL)
    {
        if (self::FILL == $display) {
            return date('h', $this->time);
        } elseif (self::DIGIT == $display) {
            return date('g', $this->time);
        }

        return date('h', $this->time);
    }

    /**
     * 获取当前日期的24小时制时间.
     *
     * @param string $display 显示类型，默认为0，显示两位的小时
     *
     * @return string
     */
    public function get24Hours($display = self::FILL)
    {
        if (self::FILL == $display) {
            return date('H', $this->time);
        } elseif (self::DIGIT == $display) {
            return date('G', $this->time);
        }

        return date('H', $this->time);
    }

    /**
     * 获取当前日期的分钟
     *
     * @return string
     */
    public function getMinutes()
    {
        return date('i', $this->time);
    }

    /**
     * 获取当前日期的秒数.
     *
     * @return string
     */
    public function getSeconds()
    {
        return date('s', $this->time);
    }

    /**
     * 获取当前日期的本地时区.
     *
     * @return string
     */
    public function getLocalTimeZone()
    {
        return date('T', $this->time);
    }

    /**
     * 重新设置当前日期与时间.
     *
     * @param string $time 时间戳
     */
    public function setTime($time)
    {
        if (is_int($time) || (is_string($time) && ($time = strtotime($time)))) {
            $this->time = $time;
        }
    }

    /**
     * 取得当前日期时间对象
     *
     * @return WindGeneralDate
     */
    public function getNow()
    {
        $date = getdate($this->time);

        return new self($date['year'], $date['mon'], $date['mday'], $date['hours'], $date['minutes'], $date['seconds']);
    }

    /**
     * 对象转化为字符串，魔术方法.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toString();
    }

    /**
     * 格式化时间输出.
     *
     * @param string $format 需要输出的格式,默认为null，则采用格式Y-m-d H:i:s
     *
     * @return string
     */
    public function toString($format = null)
    {
        return date($format ? $format : self::DEFAULT_FORMAT, $this->time);
    }

    /**
     * 判断是否是闰年.
     *
     * @return int 返回1或是0
     */
    public function isLeapYear()
    {
        return date('L', $this->time);
    }
}
